# -*- coding: utf-8 -*-
# @Organization  : asiainfo
# @Author        : 周伟东
# @Time          : 2021/1/7 9:30
# @Function      : job 对外api接口

import json
import uuid
from flask import current_app, request
from flask_restful import Resource
from app.common.common_request_porcess import req
from app.common.common_response_code import response_code
from app.common.common_response_log import ResponseLog
from app.common.common_response_process import response_result_process
from app.core.job_queue import jobQueue
from app.dao.job_dao import jobDao
from app.models import CyberspaceJob
from app.utils.ip_helper import validate_ips
from app.utils.port_helper import validate_ports


class InterfaceCreateJob(Resource):
    # 创建任务请求
    def post(self):
        """
        desc: post请求，对外的接口，接收的参数
        param: {"job_name":"xxx","ips":"xxx.xxx.xx.xx/23","ports":xxxx}
        return: {"code":200, data:{"job_id":"xxxxxxx"}, msg="成功"}
        """
        request_data = req.request_process(request)
        # step1. 校验参数
        response = self.__validate_params(request_data)
        if response:
            return response
        # step2. 生成Job 插入到数据库
        job_id = ''.join(str(uuid.uuid4()).split('-'))
        try:
            job_params = json.dumps(request_data)
            cyberspace_job = CyberspaceJob(job_id=job_id,
                                           job_name=request_data["job_name"],
                                           job_type=request_data["job_type"],
                                           job_creator=request_data["job_creator"],
                                           job_params=job_params,
                                           job_create_time=CyberspaceJob.get_time(),
                                           org_id=request_data["org_id"],
                                           tenant_id=request_data["tenant_id"])
            jobDao.save(cyberspace_job)
            current_app.logger.info("任务: {job_id} 添加成功".format(job_id=job_id))
        except Exception as e:
            current_app.logger.error("任务: {job_id} 添加任务失败".format(job_id=job_id), e)
            return response_code.ADD_JOB_FAIL

        # step3. 添加任务进入任务队列
        if not jobQueue.addJob(job_id):
            # 修改任务为失败状态
            jobDao.update_job_status_failed(job_id)
            return response_code.SERVER_IS_BUSY
        response = response_code.SUCCESS
        response["data"] = {"job_id": job_id}
        return response

    def __validate_params(self, request_data):
        """
         desc: 对接收过来的参数进行校验
         param: request_data 接收过来的参数，包含ips、ports、job_name、job_creator、org_id、tenant_id, job_type
         return
        """
        # 1.request_data 类型校验
        if isinstance(request_data, bool):
            request_data = response_code.REQUEST_PARAM_FORMAT_ERROR
            return response_result_process(request_data)
        # 2. 参数不为空
        if not request_data:
            data = response_code.REQUEST_PARAM_MISSED
            return response_result_process(data)
        # 3. 必须包含ips 和 ports
        fields = ['job_name', 'job_creator', 'ips', 'ports', 'org_id', 'tenant_id', 'job_type']
        must = req.verify_all_param_must(request_data, fields)
        if must:
            return response_result_process(must)
        # 4. 参数类型校验
        par_type = {'job_name': str, 'job_creator': str, 'ips': str,
                    'ports': str, 'org_id': int, 'tenant_id': int, 'job_type': int}
        param_type = req.verify_all_param_type(request_data, par_type)
        if param_type:
            return response_result_process(param_type)
        # 5. job_name、ips以及ports校验
        job_name = request_data["job_name"]
        ips = request_data["ips"]
        # 如果为空，扫描全端口
        if len(request_data['ports']) == 0:
            request_data['ports'] = "1-65535"
        ports = request_data['ports']
        if 0 >= len(job_name) > 20:
            response = response_code.BAD_REQUEST
            response['msg'] = ResponseLog.wrong_param_length(job_name, 1, 20)
            return response
        if not validate_ips(ips):
            response = response_code.BAD_REQUEST
            response['msg'] = ResponseLog.wrong_param_format(ips)
            return response
        if not validate_ports(ports):
            response = response_code.BAD_REQUEST
            response['msg'] = ResponseLog.wrong_param_format(ports)
            return response
        return None
